package io.github.biezhi.elves.spider;

import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

import javax.annotation.Resource;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import io.github.biezhi.elves.common.Constants;
import io.github.biezhi.elves.common.CookieConstants;
import io.github.biezhi.elves.model.CompBasic;
import io.github.biezhi.elves.model.QccCookie;
import io.github.biezhi.elves.ok.http.FastHttpClient;
import io.github.biezhi.elves.property.CityProperty;
import io.github.biezhi.elves.service.CompService;
import io.github.biezhi.elves.utils.StringUtils;

@Service
public class CompSpider {
	@Resource
	private CityProperty cityProperty;
	private static CityProperty staticCityProperty;
	
	@Resource
	private CompService compService;
	private static CompService staticCompService;

	@Bean
	public CityProperty getCityPropertyBean(){
		if(cityProperty!=null){
			staticCityProperty = cityProperty;
			return staticCityProperty;
		}
		return null;
	}
	
	@Bean
	public CompService getCompServiceBean(){
		if(compService!=null){
			staticCompService = compService;
			return staticCompService;
		}
		return null;
	}
	
	static int pageNo = 1;
	static int pageSize = 20;
	final String indexUrl = "http://www.qichacha.com";
	static String cookieVal = CookieConstants.QYY_CCA_COOKIE;
	
	public CompSpider(){}

	/**
	 * 开始根据执行企业名称批量更新企业地址、logo、简介
	 * @throws Exception 
	 */
	public void startQccCompAddrAndLogoAndDesc() throws Exception{
		int pageNum = 0;
		while(true){
			pageNum++;
			//根据企业名称批量更新企业地址、logo、简介
			batchUpdateCompAddrAndLogoAndDescData(pageNum, 1);
		}
	}
	
	/**
	 * 根据企业名称批量更新企业地址、logo、简介
	 * @param pageNum
	 * @param cityId
	 * @param requestUrl
	 */
	@SuppressWarnings("deprecation")
	public void batchUpdateCompAddrAndLogoAndDescData(int pageNum, Integer cityId) {
		//企业数据获取
		try{
			System.out.println(this.getClass() + ".batchUpdateCompAddrAndLogoAndDescData[{}]==>当前页数:" + pageNum + "，每页显示记录数:" + pageSize);
			//获取法人代表数据(分页)
			List<CompBasic> compBasicPageList = compService.listCompBasicPageByCityId(pageNum,pageSize,cityProperty.getAppCityId());
			if(compBasicPageList!=null && compBasicPageList.size() > 0) {
				int index = 0;
				for(CompBasic compBasic : compBasicPageList) {
					index++;
					String compName = compBasic.getCompName();
					System.out.println("======开始新增第" + index + "条，" + compName + "企业数据=====");
					System.out.println();
					
//					compName = "广州柏尔其进出口有限公司";
//					compName = "广州市惜时贸易有限公司";
//					compName = "广州市逖美电子科技有限公司";
//					compName = "广州市捷诚电子科技有限公司";
					String compNameEncode = URLEncoder.encode(compName);
					String httpUrl = indexUrl + "/search?key=" + compNameEncode;
					String responseBody = getHttpForDataContent(httpUrl);
					if(!StringUtils.isNullOrEmpty(responseBody)) {
//						System.out.println(responseBody);
						Document doc = Jsoup.parse(responseBody);
						Elements elements = doc.select("#searchlist > table > tbody > tr");
						if(elements!=null && elements.size()>0){
							String compLogo = "";
							String compTelphone = "";
							String compNet = "";
							String compEmail = "";
							String compAddr = "";
							String compDesc = "";
							for(Element element : elements){
								String entname = element.select("td").get(1).select("a.ma_h1").text();
								if(!entname.trim().equals(compName)) {
									this.compService.updateCompBasicData(new CompBasic(compBasic.getCompId(), "", "", "", "", ""));
								} else {
									String compUrl = element.select("td").get(1).select("a").attr("href");
									String hrefUrl = indexUrl + compUrl;
									responseBody = getHttpForDataContent(hrefUrl);
									if(!StringUtils.isNullOrEmpty(responseBody)) {
//										System.out.println(responseBody);
										
										doc = Jsoup.parse(responseBody);
										elements = doc.select("#company-top > .row");
										
										if(elements!=null && elements.size()>0){
											for(Element compElement : elements){
												compLogo = compElement.select(".logo > .imgkuang > img").attr("src");
												compLogo = compLogo.contains("default.jpg") ? "" : compLogo;
												
												Elements rowElements = compElement.select(".content > .row");
												ListIterator<Element> result = rowElements.listIterator();
											     
									            while(result.hasNext()) {
									                Element get = result.next();
									                String para = get.text();
									                para = para.replace(" 更多号码", "").replace(" 流量分析", "").replace(" 附近公司", "");
									                
									                if(!para.contains("电话：") && !para.contains("官网：") && !para.contains("地址：")) {
									                	continue;
									                }
									                
									                String[] paras = para.split("：");
									                String paraString = Arrays.toString(paras);
									                paraString = paraString.replace("  ", "");
//									                System.out.println(Arrays.toString(paras));
//									                System.out.println(paraString);
									                
									                String[] paraStringArray = paraString.split(" ");
//									                System.out.println(Arrays.toString(paraStringArray));
									                for(int i = 0; i < paraStringArray.length; i++) {
									                	String paraStr = paraStringArray[i];
									                	if(paraStr.contains("电话")) {
									                		compTelphone = paraStr.split(",")[1];
									                		compTelphone = compTelphone.replace("暂无", "");
									                	} else if(paraStr.contains("官网")) {
									                		compNet = paraStr.split(",")[1];
									                		compNet = compNet.replace("暂无", "").replace("]", "");
									                	} else if(paraStr.contains("地址")) {
									                		if("暂无".equals(paraStr.split(",")[1])) {
									                			compAddr = paraStr.split(",")[1];
										                		compAddr = compAddr.replace("暂无", "").replace("]", "");
									                		} else {
										                		String compAddrHtml = get.html();
										                		Document compAddrDoc = Jsoup.parse(compAddrHtml);
																Elements compAddrElements = compAddrDoc.select(".cvlu > a");
																ListIterator<Element> compAddrResult = compAddrElements.listIterator();
															     
													            while(compAddrResult.hasNext()) {
													                Element compAddrGet = compAddrResult.next();
													                String compAddrClickShowMapModal = compAddrGet.attr("onclick");
													                if(compAddrClickShowMapModal.contains("showMapModal")) {
													                	String[] compAddrAttrClickArray = compAddrClickShowMapModal.split(";");
													                	String compAddrAttrClickString = compAddrAttrClickArray[0];
																		compAddrAttrClickString = compAddrAttrClickString.replace("showMapModal('", "").replace("','')", "");
//																		System.out.println(compAddrAttrClickString);
												                		compAddr = compAddrAttrClickString;
												                		compAddr = compAddr.replace("暂无", "").replace("]", "");
												                		break;
													                } else {
													                	continue;
													                }
													            }
																
									                		}
									                	}
									                }
//									                System.out.println(para);
									            }
											}
										}
										Elements compDescElements = doc.select("#jianjieModal");
										if(compDescElements!=null && compDescElements.size()>0){
											Element compDescElement = compDescElements.get(0);
											compDesc = compDescElement.select("#textShowMore").text();
										}
										
										CompBasic compBasicResult = new CompBasic(compBasic.getCompId(),compLogo,compTelphone,compNet,compAddr,compDesc);
										System.out.println(JSON.toJSONString(compBasicResult));
										this.compService.updateCompBasicData(compBasicResult);
									}
									break;
								}
							}
						}
					}
				}
				
				//查询企业表已更新logo数量数
				int countCompBasic = compService.countCompBasicUpdateLogo(cityProperty.getAppCityId());
				System.err.println("共要补充数据量为{{}}==>" + compBasicPageList.size());
				System.err.println("已更新企业数据量{{}}==>" + countCompBasic);
			} else {
				System.out.println();
				System.out.println("======已完成企业数据补充，系统自动停止======");
				System.exit(0);
			}
		}catch(Exception e){
			System.out.println("企业数据异常{{}}==>" + e.getMessage());
		}
	}
	
	/**
	 * 通过http方式，获取html数据
	 * @param requestUrl
	 * @return
	 */
	private String getHttpForDataContent(String requestUrl) {
		String responseBody = getHttpReponseBody(requestUrl);
		return responseBody;
	}
	
	/**
	 * 返回响应url内容
	 * @param requestUrl
	 * @return
	 */
	String proxyIp = Constants.PROXY_IP;
	int proxyPort = Constants.PROXY_PORT;
	private String getHttpReponseBody(String requestUrl){
		String jsonStr = "";
		try {
			System.out.println("获取url内容时，先休眠5000毫秒......");
			Thread.sleep(5000);
			System.out.println("已休眠5000毫秒，开始获取url内容===>");
			String qccCookie = CookieConstants.QYY_CCA_COOKIE;
//			System.out.println(this.getClass() + ".getHttpReponseBody方法，qccCookie{{}}==>" + qccCookie);
			
//			String proxyIp = Constants.PROXY_IP;
//			int proxyPort = Constants.PROXY_PORT;
			
			if("132.122.1.4".equals(proxyIp) && proxyPort == 9898) {
				resetProxyIp();
			}
			
			io.github.biezhi.elves.ok.http.Response okHttpResponse;
			if(!Constants.IS_PROXY){
				okHttpResponse = FastHttpClient
						.get()
						.addHeader("cookie", qccCookie)
						.url(requestUrl)
						.build()
						.execute();
			}else{
				Proxy proxy = new Proxy(Proxy.Type.HTTP,new InetSocketAddress(proxyIp, proxyPort));
				okHttpResponse = FastHttpClient
						.newBuilder()
						.proxy(proxy)
						.build()
						.get().addHeader("cookie", qccCookie)
						.url(requestUrl)
						.build()
						.execute();
			}
			jsonStr = okHttpResponse.string();
			if("[]".equals(jsonStr)){
				jsonStr = "";
			}
			//判断是否为json格式
			boolean isJson = StringUtils.isJsonFormat(jsonStr);
			if(!isJson){
				String scriptRequestUrl = "";
				String scriptRequestUrl1 = requestUrl.replace("http://www.qichacha.com/", "http://www.qichacha.com/index_verify?type=companysearch&back=/");
				String scriptRequestUrl2 = requestUrl.replace("http://www.qichacha.com/", "https://www.qichacha.com/index_verify?type=companysearch&back=/");
				String scriptStr1 = "<script>window.location.href='" + scriptRequestUrl1 +"';</script>";
				String scriptStr2 = "<script>window.location.href='" + scriptRequestUrl2 +"';</script>";
				
				if(scriptStr1.equals(jsonStr)){
					System.out.println("过于频繁调用企查查，超出企查查询次数......");
//					System.out.println("过于频繁调用企查查，超出企查查询次数，暂时休眠，需人工干预，休眠10000毫秒......");
//					Thread.sleep(10000);
					
					scriptRequestUrl = scriptRequestUrl1;
					Constants.QCC_PAQU_STATE = "1";
					resetQccCookie();
					resetProxyIp();
					//重置企查查cookie
					jsonStr = getHttpReponseBody(scriptRequestUrl);
				} else if(scriptStr2.equals(jsonStr)) {
					System.out.println("过于频繁调用企查查，超出企查查询次数......");
//					System.out.println("过于频繁调用企查查，超出企查查询次数，暂时休眠，需人工干预，休眠10000毫秒......");
//					Thread.sleep(10000);
					
					scriptRequestUrl = scriptRequestUrl2;
					Constants.QCC_PAQU_STATE = "1";
					resetQccCookie();
					resetProxyIp();
					//重置企查查cookie
					jsonStr = getHttpReponseBody(scriptRequestUrl);
				} else {
					if(StringUtils.isNullOrEmpty(jsonStr)){
						System.out.println("过于频繁调用企查查，超出企查查询次数......");
						Constants.QCC_PAQU_STATE = "2";
						resetQccCookie();
						resetProxyIp();
						jsonStr = getHttpReponseBody(scriptRequestUrl);
					}else{
						Document doc = Jsoup.parse(jsonStr);
						Elements normalLoginElements = doc.select("#normalLoginPanel");
						if((normalLoginElements!=null && normalLoginElements.size()>0)){
							System.out.println("过于频繁调用企查查，超出企查查询次数，登录页面......");
							Constants.QCC_PAQU_STATE = "2";
							resetQccCookie();
							resetProxyIp();
							jsonStr = getHttpReponseBody(requestUrl);
						} else {
							Elements titleElements = doc.select("title");
							if(titleElements!=null && titleElements.size() > 0) {
								String title = titleElements.get(0).select("title").text();
								if("用户验证_企查查".equals(title)) {
									System.out.println("过于频繁调用企查查，超出企查查询次数，请按住滑块，拖动到最右边......");
									Constants.QCC_PAQU_STATE = "2";
									resetQccCookie();
									resetProxyIp();
									jsonStr = getHttpReponseBody(requestUrl);
								}
							}
						}
					}
				}
			}
		} catch (SocketTimeoutException e) {
			System.err.println("io.github.biezhi.elves.spider.getHttpReponseBody，SocketTimeoutException，返回响应url内容，链接串为:" + requestUrl + "{{}}==>" + StringUtils.getErrorInfoFromException(e));
			
			if(Constants.IS_PROXY){
				System.out.println("io.github.biezhi.elves.spider.getHttpReponseBody，网络超时，休眠5000毫秒后，重新再调用......");
				try {
					Thread.sleep(5000);
					System.out.println("io.github.biezhi.elves.spider.getHttpReponseBody，已休眠5000毫秒，开始重新再调用getHttpReponseBody方法===>");
					resetProxyIp();
					getHttpReponseBody(requestUrl);
				} catch (InterruptedException e1) {
					e1.printStackTrace();
				}
			}
		} catch (Exception e) {
			System.err.println("io.github.biezhi.elves.spider.getHttpReponseBody，返回响应url内容，链接串为:" + requestUrl + "{{}}==>" + StringUtils.getErrorInfoFromException(e));
			
			System.out.println("io.github.biezhi.elves.spider.getHttpReponseBody，休眠5000毫秒后，重新再调用......");
			try {
				Thread.sleep(5000);
				System.out.println("io.github.biezhi.elves.spider.getHttpReponseBody，已休眠5000毫秒，开始重新再调用getHttpReponseBody方法===>");
				resetProxyIp();
				getHttpReponseBody(requestUrl);
			} catch (InterruptedException e1) {
				e1.printStackTrace();
			}
		}
		return jsonStr;
	}
	
	private void resetProxyIp() {
		try{
			Map<String,Object> proxyIpMap = StringUtils.getHttpProxyIp(1);
			String proxyJson = JSONObject.toJSONString(proxyIpMap);
			System.out.println(proxyJson);
			proxyIp = StringUtils.getValueForKey("proxyHost", proxyIpMap);
			proxyPort = StringUtils.getIntValueForKey("proxyPort", proxyIpMap);
			
			System.out.println("代理ip{{}}==>" + proxyIp + "，代理端口{{}}==>" + proxyPort);
		} catch (Exception e) {
			System.err.println("获取第三方代理ip接口异常{{}}==>" + StringUtils.getErrorInfoFromException(e));
		}
	}
	
	/**
	 * 重置企查查cookie
	 */
	private String resetQccCookie() {
		System.out.println("===企查查爬取状态{{}}==>" + Constants.QCC_PAQU_STATE);
		if(!"0".equals(Constants.QCC_PAQU_STATE)) {
			QccCookie qccCookie = this.compService.findQccCookie();
			if(qccCookie!=null) {
				System.out.println("=====替换" + qccCookie.getPhone() + "，账户的cookie信息");
				CookieConstants.QYY_CCA_COOKIE = qccCookie.getQccCookie();
				
				System.out.println("=====更新此账户" + qccCookie.getPhone() + "，cookie信息使用值为T");
//				this.compService.updateQccCookieIsUse(qccCookie.getQccId());
				
				System.out.println("=====重置企查查爬取状态为0");
				Constants.QCC_PAQU_STATE = "0";
			}
		}
		return CookieConstants.QYY_CCA_COOKIE;
	}
}